vue3-axios封装
安装依赖
安装本体依赖 npm i axios -S
报错提示用到了 element-plus
依赖作为报错提醒的工具,需要提前安装 npm i element-plus -S
封装实例
创建 axios/index.ts
,只需要考虑单一职责,这块只封装 axios 实例,参考文档
引入依赖
ts
import axios, { AxiosRequestConfig } from 'axios';
import { ElMessage } from 'element-plus';
定义报错处理方法
ts
const errorHandle = (status: number) => {
switch (status) {
case 302:
ElMessage.error('接口重定向了!==>' + status);
break;
case 400:
ElMessage.error('发出的请求有错误,服务器没有进行新建或修改数据的操作==>' + status);
break;
case 404:
ElMessage.error('网络请求不存在==>' + status);
break;
case 406:
ElMessage.error('请求的格式不可得==>' + status);
break;
case 408:
ElMessage.error(' 请求超时!==>' + status);
break;
case 410:
ElMessage.error('请求的资源被永久删除,且不会再得到的==>' + status);
break;
case 422:
ElMessage.error('当创建一个对象时,发生一个验证错误==>' + status);
break;
case 500:
ElMessage.error('服务器发生错误,请检查服务器==>' + status);
break;
case 502:
ElMessage.error('网关错误==>' + status);
break;
case 503:
ElMessage.error('服务不可用,服务器暂时过载或维护==>' + status);
break;
case 504:
ElMessage.error('网关超时==>' + status);
break;
default:
ElMessage.error('发生未知错误==>' + status);
}
};
移除重复请求
ts
// 定义接口
interface PendingType {
url?: string;
method?: string;
params: any;
data: any;
cancel: any;
}
// 取消重复请求
const pending: Array<PendingType> = [];
const CancelToken = axios.CancelToken;
// 移除重复请求
const removePending = (config: AxiosRequestConfig) => {
pending.forEach((list: PendingType, index: number) => {
const isEqualConfig = list.url === config.url && list.method === config.method;
const isEqualParams = JSON.stringify(list.params) === JSON.stringify(config.params);
const isEqualData = JSON.stringify(list.data) === JSON.stringify(config.data);
if (isEqualConfig && isEqualParams && isEqualData) {
list.cancel('操作太频繁,请稍后再试'); // 执行取消操作
pending.splice(index, 1); // 从数组中移除记录
}
});
};
创建实例
ts
const instance = axios.create({
headers: {
// 'Content-Type': 'application/json;charset=UTF-8',
},
timeout: 1000 * 30, // 超时时间
baseURL: '/api', // 请求的 base 地址
withCredentials: false, // 表示跨域请求时是否需要使用凭证
});
请求拦截器
ts
instance.interceptors.request.use(
config => {
removePending(config);
config.cancelToken = new CancelToken((c) => {
pending.push({
url: config.url,
method: config.method,
params: config.params,
data: config.data,
cancel: c,
});
});
return config;
},
error => {
ElMessage.error(error.data.error.message);
return Promise.reject(error.data.error.message);
}
);
响应拦截器
ts
instance.interceptors.response.use(
(config) => {
removePending(config.config);
if (config.status === 200 || config.status === 204) {
return Promise.resolve(config);
} else {
return Promise.reject(config);
}
},
(error) => {
const { response } = error;
if (response) {
errorHandle(response.status);
const config = error.config; // 超时重新请求
const [RETRY_COUNT, RETRY_DELAY] = [3, 1000]; // 全局的请求次数,请求的间隙
if (config && RETRY_COUNT) {
config.__retryCount = config.__retryCount || 0; // 记录重试次数
// 检查是否已经把重试的总数用完
if (config.__retryCount >= RETRY_COUNT) {
return Promise.reject(response || { message: error.message });
}
// 指数后退重试
config.__retryCount++; // 计数加1
const backoff = new Promise<void>((resolve) => {
setTimeout(() => {
resolve();
}, RETRY_DELAY || 1);
});
return backoff.then(() => {
return instance(config);
});
}
return Promise.reject(response);
} else {
ElMessage.error('请求失败,请检查网络连接是否正常');
}
}
);
导出实例
ts
export default instance;